package com.webex.ta.hydra.gui.table;

import com.webex.ta.hydra.core.Command;
import com.webex.ta.hydra.util.HydraUtils;

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-8-25
 * Time: 14:49:41
 */
public class ExpansionToggleBorder implements Border {
    static final Icon COLLAPSE_ICON;
    static final Icon EXPAND_ICON;
    static final int ICON_WIDTH = 16;
    static final Color TREE_COLOR = 	new Color(122,138,153);

    static final int LEVEL_WIDTH = 20;

    private Command cmd;
    private boolean error;


    static final Icon ERR_BG;
    static final int BG_WIDTH;

    static final int GAP = 4;

    static {
        COLLAPSE_ICON = HydraUtils.getImage("group-collapse.png");
        EXPAND_ICON = HydraUtils.getImage("group-expand.png");
        ERR_BG = HydraUtils.getImage("errcheck_bg.gif");
        BG_WIDTH = ERR_BG.getIconWidth();
    }

    public ExpansionToggleBorder(Command cmd, Color color, boolean error) {
        this.cmd = cmd;
        this.error = error;
    }

    private int expandIconPosX(int x, int y, int width, int height) {
        return x + cmd.getIndent() * LEVEL_WIDTH;
    }

    private int expandIconPosY(int x, int y, int width, int height) {
        return y + (height - EXPAND_ICON.getIconHeight()) / 2;
    }

    private void paintExpandIcon(Component c, Graphics g,
                                 int x, int y, int width, int height) {
        int xpdOffsetX = expandIconPosX(x, y, width, height);
        int xpdOffsetY = expandIconPosY(x, y, width, height);

        if (!cmd.isExpanded()) { // node is collapsed
            EXPAND_ICON.paintIcon(c, g,
                    xpdOffsetX,
                    xpdOffsetY);
        } else { // node is expanded
            COLLAPSE_ICON.paintIcon(c, g,
                    xpdOffsetX,
                    xpdOffsetY);
            g.setColor(Color.black);
        }
    }

    private void paintCommandIcon(Component c, Graphics g,
                                 int x, int y, int width, int height) {
        int posX = expandIconPosX(x, y, width, height) + ICON_WIDTH + GAP;
        int posY = expandIconPosY(x, y, width, height);
        Icon icon = HydraUtils.getIconForCommand(cmd);
        if (icon != null)
            icon.paintIcon(c, g, posX, posY);
    }

    private void paintTree(Component c, Graphics g,
                                 int x, int y, int width, int height) {
        Rectangle oldBounds = g.getClipBounds();
        Rectangle newBounds = new Rectangle(oldBounds);
        newBounds.height++;
        g.setClip(newBounds);
        g.setColor(TREE_COLOR);
        // draw horizontal line
        if (cmd.getIndent() > 0 || cmd.hasChild()) {
            int startX = expandIconPosX(x, y, width, height) + ICON_WIDTH / 2;
            int startY = height / 2;
            int endX = startX + GAP + ICON_WIDTH;
            int endY = startY;
            g.drawLine(startX, startY, endX, endY);
        }

        //draw vertical lines
        if (cmd.hasChild() && cmd.isExpanded()) {
            int startX = cmd.getIndent() * LEVEL_WIDTH + ICON_WIDTH + GAP + ICON_WIDTH / 2;
            int endX = startX;
            int startY = height / 2;
            int endY = height;
            g.drawLine(startX, startY, endX, endY);
        }

        // recursively visit parent
        if (cmd.hasParent())
            drawVerticalLine(cmd.getParent(), cmd.getIndent(), g, x, y, width, height);

        if (cmd.hasParent() && cmd.getIndent() > 0) {
            int startX = cmd.getIndent() * LEVEL_WIDTH + ICON_WIDTH / 2;
            int endX = startX;
            int startY = 0;
            int endY = height;
            if (cmd.hasNextSibling()) {
                // draw from top to bottom
                g.drawLine(startX, startY, endX, endY);
            } else {
                g.drawLine(startX, startY, endX, endY/2);
            }
        }
        g.setClip(oldBounds);
    }

    private void drawVerticalLine(Command aCmd, int indent, Graphics g,
                                 int x, int y, int width, int height) {
        if (aCmd.hasNextSibling() && indent > 1) {
            int startX = indent * LEVEL_WIDTH - ICON_WIDTH/2 - GAP;
            int endX = startX;
            g.drawLine(startX, 0, endX, height);
        }
        if (indent > 1 && cmd.hasParent()) {
            drawVerticalLine(aCmd.getParent(), indent-1, g, x, y, width, height);
        }
    }


    public void paintBorder(Component c, Graphics g,
                            int x, int y, int width, int height) {

        paintTree(c, g, x, y, width, height);

        if (cmd.hasChild()) {
            paintExpandIcon(c, g, x, y, width, height);
        }

        paintCommandIcon(c, g, x, y, width, height);

        if (error) {
            for (int i = 0; i < width / BG_WIDTH; i++) {
                ERR_BG.paintIcon(c, g, ERR_BG.getIconWidth() * i, y + height - ERR_BG.getIconHeight());
            }
        }
    }

    public Insets getBorderInsets(Component c) {
        return new Insets(0, cmd.getIndent() * LEVEL_WIDTH
                + ICON_WIDTH + GAP + ICON_WIDTH + GAP, 0, 1);
    }

    public boolean isBorderOpaque() {
        return false;
    }

    public static boolean isExpansionToggle(int level, int x) {
        return (x >= level * LEVEL_WIDTH)
                && (x <= level * LEVEL_WIDTH + ICON_WIDTH);
    }

//    private Icon getIconForCommand(Command cmd) {
//        Icon icon;
//        if (HydraUtils.isController(cmd)) {
//            if (cmd.isExpanded())
//                icon = HydraUtils.getImage("fldr_obj.gif");
//            else
//                icon = HydraUtils.getImage("folder.gif");
//        } else if (HydraUtils.isProcessor(cmd)) {
//            icon = HydraUtils.getImage("processor.gif");
//        } else {
//            icon = HydraUtils.getImage("runtime.gif");
//        }
//        if (!cmd.isEnabled())
//            icon = UIManager.getLookAndFeel().getDisabledSelectedIcon(null, icon);
//        return icon;
//    }
}

